home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / minix / update~4.z / update~4 / lib_stdio_fwrite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-06  |  3.7 KB  |  134 lines

  1. /*            f w r i t e
  2.  *
  3.  * This function writes a series of records to the output stream.
  4.  * The function returns the number of items written to the stream.
  5.  * Writing stops when the correct number of items have been written
  6.  * or when the function encounters an error.
  7.  *
  8.  * Patchlevel 1.1
  9.  *
  10.  * Edit History:
  11.  * 05-Sep-1989    Include limits.h if INT_MAX undefined so removing
  12.  *        need to define MINIX when compiling. Assign void *
  13.  *        to unsigned char * to avoid casting problems.
  14.  * 04-Sep-1989    Add code to deal with really large objects.
  15.  * 03-Sep-1989    Write to buffer only if it requires at most one call
  16.  *        to write(), otherwise use write() directly.
  17.  * 01-Sep-1989    Use Collyer's idea to speed up by doing writes directly
  18.  *        from buffer.
  19.  */
  20.  
  21. #include "stdiolib.h"
  22.  
  23. #if    defined(BSD)
  24. # include <values.h>
  25. # define INT_MAX    (MAXINT)
  26. #endif
  27.  
  28. #if    !defined(INT_MAX)
  29. # include <limits.h>
  30. #endif
  31.  
  32. /*LINTLIBRARY*/
  33.  
  34. int fwrite(ptr, size, nitems, fp)
  35.  
  36. CONST void *ptr;                /* buffer */
  37. unsigned int size;                /* size of item */
  38. unsigned int nitems;                /* number of items */
  39. FILE *fp;                    /* stream */
  40.  
  41. {
  42.   int wrote;                /* bytes written in write call */
  43.   int write();                /* write call */
  44.   unsigned char *p;            /* buffer pointer */
  45.  
  46. /* Phase 1 --- Amount to write overflows INT_MAX */
  47.   unsigned int burstsize;        /* size aligned chunk to write */
  48.   unsigned int itemsperburst;        /* items written per burst */
  49.   unsigned int itemsleft;        /* items left */
  50.  
  51. /* Phase 2 --- Write remainder */
  52.   unsigned int bytestotal;        /* total number of bytes */
  53.   unsigned int bytesleft;        /* total number of bytes left */
  54.   unsigned int copybytes;        /* bytes to copy */
  55.   unsigned char *q;            /* pointer into putc buffer */
  56.  
  57. /* Items left to write */
  58.   if ((itemsleft = nitems) == 0 || size == 0)
  59.     return 0;
  60.  
  61. /* Fix void * casting problems */
  62.   p = (unsigned char *) ptr;
  63.  
  64. /* Very large objects */
  65.   if ((itemsperburst = INT_MAX / size) == 0) {
  66.     (void) fflush(fp);
  67.     do {
  68.       bytesleft = size;
  69.       do {
  70.     if ((burstsize = INT_MAX) > bytesleft)
  71.       burstsize = bytesleft;
  72.     if ((wrote = write(fileno(fp), (char *) p, (int) burstsize)) !=
  73.         burstsize)
  74.       return (nitems-itemsleft);
  75.     p += burstsize;
  76.       } while ((bytesleft -= burstsize) != 0);
  77.     } while (--itemsleft);
  78.     return nitems;
  79.   }
  80.  
  81. /* Write large amounts of data for small objects */
  82.   for (burstsize = itemsperburst * size; itemsleft > itemsperburst; ) {
  83.     if (itemsleft == nitems)
  84.       (void) fflush(fp);
  85.     if ((wrote = write(fileno(fp), (char *) p, (int) burstsize)) != burstsize) {
  86.       if (wrote == -1)
  87.     wrote = 0;
  88.       return (nitems-itemsleft) + (wrote/size);
  89.     }
  90.     p += burstsize;
  91.     itemsleft -= itemsperburst;
  92.   }
  93.  
  94. /* At this point itemsleft contains the number of items left to
  95.  * write. The output buffer may not be empty. itemsleft*size
  96.  * will not overflow INT_MAX.
  97.  */
  98.  
  99.   if ((bytesleft = bytestotal = size*itemsleft) != 0) {
  100.  
  101. /* Unallocated buffer */
  102.     if (! HASBUFFER(fp)) {
  103.       if (_allocbuf(fp) < 0)
  104.     return (nitems-itemsleft);
  105.       SETIOFLUSH();
  106.     }
  107.  
  108. /* Partially filled write buffer */
  109.     if (! TESTFLAG(fp, _IONBF) &&
  110.     bytesleft <= UNUSEDINWRITEBUFFER(fp) + BUFFERSIZE(fp)) {
  111.       do {
  112.     if ((copybytes = UNUSEDINWRITEBUFFER(fp)) > bytesleft)
  113.       copybytes = bytesleft;
  114.     wrote = copybytes;
  115.     q = GETWRITEPTR(fp);
  116.     UNROLL_DO(fwritebytes, copybytes, *q++ = *p++);
  117.     SETWRITEPTR(fp, q);
  118.     if (bytesleft > wrote && fflush(fp) == EOF)
  119.       break;
  120.       } while ((bytesleft -= wrote) != 0);
  121.  
  122.       if (TESTFLAG(fp, _IOLBF) && bytesleft == 0)
  123.     (void) fflush(fp);
  124.     }
  125.  
  126. /* Dump rest of object directly to file */
  127.     else if (fflush(fp) != EOF &&
  128.          (wrote = write(fileno(fp), (char *) p, (int) bytesleft)) != -1)
  129.       bytesleft -= wrote;
  130.   }
  131.  
  132.   return (nitems-itemsleft) + (bytestotal-bytesleft)/size;
  133. }
  134.